package com.isyscore.os.metadata.utils;

import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;
import com.isyscore.common.exception.BusinessException;
import com.isyscore.os.metadata.enums.TaskPeriodUnit;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

public class CronUtils {

    /**
     * 每分钟
     * @return
     */
    public static String everyMinute(LocalDateTime time, Integer interval) {
        if (interval == 1) {
            return time.format(DateTimeFormatter.ofPattern("ss * * * * ?"));
        } else {
            return time.format(DateTimeFormatter.ofPattern("ss ?/? * * * ?"))
                    //分钟除以间隔取余数
                    .replaceFirst("\\?", String.valueOf(time.getMinute() % interval==0?interval:time.getMinute() % interval))
                    .replaceFirst("\\?", interval.toString());
        }
    }


    /**
     * 每小时
     * @return
     */
    public static String everyHour(LocalDateTime time, Integer interval) {
        if (interval == 1) {
            return time.format(DateTimeFormatter.ofPattern("ss mm * * * ?"));
        } else {
            return time.format(DateTimeFormatter.ofPattern("ss mm ?/? * * ?"))
                    //小时除以间隔取余数
                    .replaceFirst("\\?", String.valueOf(time.getHour() % interval==0?interval:time.getHour() % interval))
                    .replaceFirst("\\?", interval.toString());
        }
    }


    /**
     * 每天
     *
     * @return
     */
    public static String everyDay(LocalDateTime time, Integer interval) {
        if (interval == 1) {
            return time.format(DateTimeFormatter.ofPattern("ss mm HH * * ?"));
        } else {
            return time.format(DateTimeFormatter.ofPattern("ss mm HH ?/? * ?"))
                    //天除以间隔取余数
                    .replaceFirst("\\?", String.valueOf(time.getDayOfMonth() % interval==0?interval:time.getDayOfMonth() % interval))
                    .replaceFirst("\\?", interval.toString());
        }
    }


    /**
     * 每月
     *
     * @return
     */
    public static String everyMonth(LocalDateTime time, Integer interval) {
        if (interval == 1) {
            String cronStr = "";
            //指定天大于28特殊处理，取当月最后一天
            if (time.getDayOfMonth() >= 28) {
                cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH ? * ?"));
                //第一个？替代为L表示最后一天
                cronStr = cronStr.replaceFirst("\\?", "L");
            } else {
                cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd * ?"));
            }
            return cronStr;
        } else {
            String cronStr = "";
            //指定天大于28特殊处理，取当月最后一天
            if (time.getDayOfMonth() >= 28) {
                cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH ? ?/? ?"));
                //第一个？替代为L表示最后一天
                cronStr = cronStr.replaceFirst("\\?", "L");
            } else {
                cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd ?/? ?"));
            }
            return cronStr
                    //月除以间隔取余数
                    .replaceFirst("\\?", String.valueOf(time.getMonthValue() % interval==0?interval:time.getMonthValue() % interval))
                    .replaceFirst("\\?", interval.toString());
        }
    }

    /**
     * 每年
     *
     * @return
     */
    public static String everyYear(LocalDateTime time, Integer interval) {
        if (interval == 1) {
            return time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ?"));
        } else {
            return time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ? ?/?"))
                    .replaceFirst("\\?","p")
                    //年除以间隔取余数
                    .replaceFirst("\\?", String.valueOf(time.getYear() % interval==0?interval:time.getYear() % interval))
                    .replaceFirst("\\?", interval.toString())
                    .replaceFirst("p","\\?");
        }
    }

    /**
     * 获取corn的运行频率
     * @param corn
     * @return
     */
    public static TaskPeriodUnit getCornPeriod(String corn){
        List<ZonedDateTime> list = getExecutionTimeByNum(corn, 2);
        // 计算时间差
        Duration duration = Duration.between(list.get(0), list.get(1));
        if(duration.toDays() / 30>0){
            return TaskPeriodUnit.month;
        }else if (duration.toDays() % 30>0) {
            return TaskPeriodUnit.day;
        }else if (duration.toHours() % 24>0) {
            return TaskPeriodUnit.hour;
        }else if (duration.toMinutes() % 60>0) {
            return TaskPeriodUnit.minute;
        }else{
            return TaskPeriodUnit.other;
        }
    }

    public static List<ZonedDateTime> getExecutionTimeByNum(String cronStr, Integer num) {
        CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.SPRING));
        Cron cron = parser.parse(cronStr);
        ExecutionTime time = ExecutionTime.forCron(cron);
        ZonedDateTime now = ZonedDateTime.now();
        ZonedDateTime next = getNext(time, now);
        List<ZonedDateTime> timeList = new ArrayList<>(num);
        timeList.add(next);
        for (int i = 1; i < num; i++) {
            next = getNext(time, next);
            timeList.add(next);
        }
        List<ZonedDateTime> resultList = new ArrayList<>(num);
        for (ZonedDateTime item : timeList) {
            resultList.add(item);
        }
        return resultList;
    }

    private static ZonedDateTime getNext(ExecutionTime time, ZonedDateTime current) {
        return time.nextExecution(current).orElseThrow(() -> new BusinessException("获取Next异常"));
    }

    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        //每分钟   05 51 09 * * ?
//        String everyMinute = everyMinute(now, 29);
//        System.out.println(everyMinute);
//        //每小时   05 51 09 * * ?
//        String everyHour = everyHour(now,3);
//        System.out.println(everyHour);
//        //每天    05 51 09 * * ?
//        String everyDay = everyDay(now, 6);
//        System.out.println(everyDay);
//        //每月    05 51 09 31 * ?
//        String everyMonth = everyMonth(now,2);
//        System.out.println(everyMonth);
//        //每年    05 51 09 31 03 *
        String everyYear = everyYear(now,2);
        System.out.println(everyYear);
    }
}
